import Dep from "../observer/dep";
import { Observer } from "../observer/index";
import Watcher from "../observer/watcher";

export function initState(vm) {
  const options = vm.$options;
  if (options.data) {
    debugger
    initData(vm);
  }
  if (options.computed) {
    debugger
    initComputed(vm);
  }
  if (options.watch) {
    const watch = options.watch;
    console.log(watch);
    for (const key in watch) {
      const current = watch[key];
      if (Array.isArray(current)) {
        current.forEach((item) => {
          createWatch(vm, key, item);
        });
      } else {
        createWatch(vm, key, current);
      }
    }
  }
}

function createWatch(vm, key, handler) {
  if (typeof handler === "string") {
    //如果是一个字符串，就是直接在methods上去取方法
    handler = vm[handler];
  }
  vm.$watch(key, handler);
}

function proxy(vm, target, key) {
  Object.defineProperty(vm, key, {
    get() {
      return vm[target][key];
    },
    set(newValue) {
      if (vm[target][key] === newValue) return;
      vm[target][key] = newValue;
    },
  });
}

function initData(vm) {
  let data = vm.$options.data;
  data = typeof data === "function" ? data.call(vm) : data;
  vm._data = data;
  observe(data);

  //代理_data属性，通过这个属性来将自定义的属性 代理到vm上
  for (const key in data) {
    if (Object.hasOwnProperty.call(data, key)) {
      proxy(vm, "_data", key);
    }
  }
}

export function observe(data) {
  if (data === null || typeof data != "object") return;
  if (data.__ob__ instanceof Observer) {
    return data.__ob__;
  }
  return new Observer(data);
}

function initComputed(vm) {
  let computed = vm.$options.computed;
  const watchers = (vm._computedWatchers = {});
  for (const key in computed) {
    const userDef = computed[key];
    // 判断当前getter是函数还是对象
    const getter = typeof userDef === "function" ? userDef : userDef.get;
    //创建watcher来监控各个计算属性
    watchers[key] = new Watcher(vm, getter, null, { lazy: true }); //用lazy来标识 计算watcher

    defineComputed(vm, key, userDef, getter);
  }
}

function defineComputed(vm, key, userDef, getter) {
  Object.defineProperty(vm, key, {
    configurable: true,
    enumerable: true,
    get: createComputedGetter(key),
    set: userDef.set,
  });
}

function createComputedGetter(key) {
  return function () {
    const watcher = this._computedWatchers[key]; //拿到当前的wathcer
    if (watcher.dirty) {
      watcher.evaluate();
    }
    // 让计算属性的两个依赖，也添加渲染watcher，这样可以达到让修改 修改计算属性依赖的属性修改值后，计算属性可以在页面上也变化（渲染）
    if (Dep.target) {
      //渲染watcher
      watcher.depend(); //这里必须要添加，最后都会被清空
    }
    return watcher.value;
  };
}
